using System;
using System.Data;
using System.Collections;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using Dimok.Documents.DataSets;

namespace Dimok.Documents {

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Recognition. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class Recognition {

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Custom forms. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public class CustomForms{
			public static Matrix.TextBox FindUniform(string fileName){
				const string PATTERN = @"(Uniform|Residential|Loan)";
				for( int i = 1; i < 10; i++ ){
					Matrix.TextBox tb = Matrix.FindPhrase(fileName,PATTERN,PATTERN,0,500,10,40,i);
					if( tb != null && !tb.IsEmpty && tb.AnchorEdgeFromTop < 70 )return tb;
				}
				return new Matrix.TextBox(0,0);
			}
		}
		#region Static Members

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Detect form by checking out it's structure. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="xmlMap">	DataSet with Anchor in first row and fields' coordinates in consequent
		/// 											rows (if any) </param>
		/// <param name="mxPdf">	. </param>
		///
		/// <returns>	true if it succeeds, false if it fails. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static bool DetectFormByCoord(string xmlMap,Matrix mxPdf) {
			DataSet ds = new DataSet();
			ds.ReadXml(xmlMap);
			for(int i=1;i<ds.Tables.Count;i++)
				try {
					if( IsItDoc(Utilities.AnalyseForm(mxPdf,ds.Tables[i].Rows,true)) )
						return true;
				}
				catch(NoAnchorFoundException){ continue; }
			return false;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Query if 'sd' is iterator document. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sd">	The sd. </param>
		///
		/// <returns>	true if iterator document, false if not. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static bool IsItDoc(StringDictionary sd) {
			foreach( string key in sd.Keys )
				if( string.Compare(key,sd[key],true) == 0 )return true;
			return sd.Count == 0;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Find Anchor withing given Area and Token within given Range from Anchor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="mx">					. </param>
		/// <param name="xmlMap">			DataSet with coordinates. </param>
		/// <param name="tableName">	Table to get Anchor/Token/Coordinates from. </param>
		///
		/// <returns>	true if it succeeds, false if it fails. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static bool DetectDocByCoord(Matrix mx,string xmlMap,string tableName) {
			DataSet ds = new DataSet();
			ds.ReadXml(xmlMap);
			DataSets.AnchorTokenByRange dsATR = new DataSets.AnchorTokenByRange();
			DataSets.AnchorTokenByRange.t_AnchorTokenByRangeDataTable t = new DataSets.AnchorTokenByRange.t_AnchorTokenByRangeDataTable();
			foreach(DataRow row in ds.Tables[tableName].Rows) {

				DataSets.AnchorTokenByRange.t_AnchorTokenByRangeRow rowA = dsATR.t_AnchorTokenByRange.Addt_AnchorTokenByRangeRow(
					ParseInt(row["AnchorYMax"],mx.MaxY),ParseInt(row["AnchorHeight"],mx.MaxY),
					ParseInt(row["TokenRangeUp"],5),ParseInt(row["TokenRangeDown"],row["TokenRangeUp"]),
					row["Anchor"]+"",ParseString(row["Token"],row["Anchor"]));
				Token anchor = mx.FindPhrase(rowA.Anchor,rowA.AnchorYMax,rowA.AnchorYMax-rowA.AnchorHeight);
				if(anchor == null) continue;
				string sToken = FilterToken(rowA.Token,anchor.Text);
				Token token = mx.FindPhrase(sToken,anchor.Y+rowA.TokenRangeUp,anchor.Y-rowA.TokenRangeDown,true);
				if(token == null) continue;
				return true;
			}
			return false;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Filter token. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="token">	The token. </param>
		/// <param name="anchor">	The anchor. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static string FilterToken(string token,string anchor) {
			ArrayList alTokens = new ArrayList();
			foreach( string t in token.Split('|') )
				if( string.Compare(t,anchor,true) != 0 )
					alTokens.Add(t);
			return string.Join("|",(string[])alTokens.ToArray(typeof(string)));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Parse string. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="val">	The value. </param>
		/// <param name="def">	The def. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static string ParseString(object val, object def) {
			return val == null || val.ToString() == "" ? def.ToString() : val.ToString();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Parse int. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="number">				Number of. </param>
		/// <param name="defaultValue">	Default value. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int ParseInt(object number,object defaultValue) {
			return int.Parse(number == null || number.ToString() == "" ? defaultValue.ToString() : number.ToString());
		}
		#endregion
	}
}